package yyy.ab.modules.security.permission;

import lombok.RequiredArgsConstructor;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import yyy.ab.common.utils.StringUtils;
import yyy.ab.modules.system.entity.SysMenu;
import yyy.ab.modules.system.entity.dto.SysRoleCodeUrlDto;
import yyy.ab.modules.system.mapper.SysRoleMenuMapper;
import yyy.ab.modules.system.service.SysMenuService;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 自定义权限数据源
 */
@Deprecated
//@Component
@RequiredArgsConstructor
public class AbSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {

    private final SysMenuService menuService;
    private final SysRoleMenuMapper roleMenuMapper;

    //角色资源MAP
    private static Map<String, Collection<ConfigAttribute>> roleMenuMap = null;

    /**
     * 根据参数（被拦截url）返回权限集合
     * 此方法是为了判定用户请求的url 是否在权限表中，如果在权限表中，则返回给 decide 方法，用来判定用户是否有此权限。如果不在权限表中则放行。
     *
     * @param object object 中包含用户请求的request 信息
     * @return
     * @throws IllegalArgumentException
     */
    @Override
    public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
        //获取当前请求url
        //String url = ((FilterInvocation) object).getRequestUrl();
        if (roleMenuMap == null) {//初始化roleMenuMap
            loadResources();
        }
        HttpServletRequest request = ((FilterInvocation) object).getHttpRequest();
        AntPathRequestMatcher matcher;
        String resUrl;
        for (Iterator<String> iter = roleMenuMap.keySet().iterator(); iter.hasNext(); ) {
            resUrl = iter.next();
            matcher = new AntPathRequestMatcher(resUrl);
            if (matcher.matches(request)) {
                return roleMenuMap.get(resUrl);
            }
        }
        return null;
    }

    /**
     * 加载全部资源、资源角色
     */
    private void loadResources() {
        roleMenuMap = new LinkedHashMap<>();
        Collection<ConfigAttribute> configAttributes;
        List<String> pathList = menuService.list().stream().filter(o -> !StringUtils.isNullOrEmpty(o.getPath())).map(SysMenu::getPath).collect(Collectors.toList());
        List<SysRoleCodeUrlDto> roleCodeUrlList = roleMenuMapper.findRoleCodeUrl();
        if (pathList != null && pathList.size() > 0) {
            for (String path : pathList) {
                configAttributes = new ArrayList<>();
                if (roleCodeUrlList != null && roleCodeUrlList.size() > 0) {
                    List<SysRoleCodeUrlDto> codeUrlDtoList = roleCodeUrlList.stream().filter(o -> o.getMenuPath().equals(path)).collect(Collectors.toList());
                    if (codeUrlDtoList != null && codeUrlDtoList.size() > 0) {
                        for (SysRoleCodeUrlDto dto : codeUrlDtoList) {
                            configAttributes.add(new SecurityConfig(dto.getRoleCode()));
                        }
                    }
                }
                roleMenuMap.put(path, configAttributes);
            }
        }
    }

    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return FilterInvocation.class.isAssignableFrom(clazz);
    }
}